/*
@author: wy
@file: work.11.3.go
@time: 2022/11/3 17:17
*/
package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

func main()  {

	//1、使用*号输出直角三角形
	i:=1
	b:="*"
	for i<4{
		fmt.Println(string(b))
		b+="**"
		i++
	}

	//2、输出九九乘法表
	for i:=1;i<=9;i++ {
		for m:=1;m<=i;m++ {
		var	n = m*i
		fmt.Printf("%d*%d=%d  ",i,m,n)
			//fmt.Println(int(i),"*",int(m),"=",int(n))
		}
		fmt.Println(" ") //println自动换行默认
	}



	//3、判断从键盘输入，字母数字字符是否为回文,如果将大写字符转化为小写字符，并移除多余非字母数字字符后，
	//正向读和反向读都一样，那就是回文。 无限次输入，按q退出
	//A,bc?: 1d,1C*ba  -- > abc1d1cba

TOP:
	var exit string //最后退出要用,先定义了

	fmt.Println("请随机输入一串字符我要判断它是不是回文: ")
	//NewReader是指专门读取文件的,可以读取空格,用scanf空格会被截断,空格后面的内容就没了
	inputReader := bufio.NewReader(os.Stdin)  //os.Stdin指向标准输入文件/dev/stdin，即os.Stdin是标准输入文件/dev/stdin的指针。
	//通过上面一句获取os.stdin指针所指向的文件内容,也就是下面用户所输入的标准输入
	s,_:= inputReader.ReadString('\n')  //获取用户所输入的字符串,以换行符为间隔读取上面变量的内容,把他赋给s  _是文件读取结束返回的错误或者其他错误,这里不需要
	//上面两句是语法

	fmt.Printf("你输入的字符串是: %s\n", s)  //打印一下

	a:=strings.ToLower(s)   //把s列表里的大写元素转换成小写
	r := "" 				//定义一个空字节用来存储等下处理好的列表元素
	for i := 0; i < len(a); i++ {   //处理列表里的所有元素
		if IsAlnum(a[i]) {			//定义了一个函数用来过滤不是数字和字母的元素
			r = r + string(a[i])    //转换成字符拼接成字符串
		}
	}
	fmt.Println("清除所有非数字字母的字符后并将大写字母换成小写后,你的字符串是:",r)
	//r就是清除干净的字符串,接下来对r判断是否是回文
	fmt.Println("字符串的长度是",len(r))  //这是r的长度
	s1 := make([]rune, 0, 5) //分配一个存储列表,用来存储切片后的字符,刚开始申请5的存储空间,后面计算不够就翻倍,够就节省时间 ,因为是空的实际内存为0 rune数据类型等于int32
	//由于rune可表示的范围更大，所以能处理一切字符，也包括中文字符
	for _, h := range r {  //依次取字符串r的字符,追加到定义好的存储空间内  _下标不需要,h是值(r里的每个字符对应的Ascll)
		s1 = append(s1, h)
	}
	fmt.Println("所形成的列表是:",s1)  //打印一下s1列表,这是Ascll码存储
	for i := 0; i < len(s1)/2; i++ {   //s1的长度是len(s1),判断回文是比较最前和最后是否相等,一次对比两个数所以判断len(s1)/2次就好了
		if s1[i] != s1[len(s1)-1-i] {   //为什么要转成列表?因为if不能直接通过下标切片判断两个字符是否相等
			fmt.Println("你输入的字符串不是回文")
			//return  //if不能用break所以用return返回函数值,有一个不满足直接退出结束函数
			fmt.Println("请输入q/Q键退出,或输入其它任意值继续:")
			fmt.Scanf("%s",&exit)
			fmt.Println(exit)
			if exit=="q" || exit=="Q"{
				return
			}else {
				goto TOP
			}
		} else {  //啥也不要做能顺利执行完就是回文
		}
	}
	fmt.Println("你输入的字符串是回文")  //没有被return结束掉,说明函数进行完毕,所以是回文,最后说一下
	fmt.Println("请输入q/Q键退出,或输入其它任意值继续:")
	fmt.Scanf("%s",&exit)
	fmt.Println(exit)
	if exit=="q" || exit=="Q"{
		return
	}else {
		goto TOP
	}
}

func IsAlnum(b byte) bool {   //b是字节 形参 a[i]传进来元素 只返回满足下面正则的元素 bool为真返回 为假不返回
	return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || (b >= '0' && b <= '9')
}